<template>
	<view class="carousel-box" @touchstart="onTouchStart" @touchend="onTouchEnd">
		<view class="carousel-track">
			<view v-for="(item, i) in images" :key="i" @tap="onItemTap(item)" class="carousel-item"
				:style="getStyle(i)">
				<image :src="item.img" class="carousel-img" mode="aspectFill" />
			</view>
		</view>
	</view>
</template>

<script setup>
	import {
		ref,
		watch
	} from 'vue'

	const emit = defineEmits(['onItemClick'])

	const props = defineProps({
		images: {
			type: Array,
			default: []
		}
	})

	const positions = ref([])

	watch(() => props.images, (newVal) => {
		if (newVal && newVal.length > 0) {
			positions.value = newVal.map((_, i) => i)
		}
	}, {
		immediate: true
	})

	const getRelativeIndex = (i) => {
		const centerIndex = positions.value.indexOf(0)
		const diff = i - centerIndex
		if (diff > props.images.length / 2) return diff - props.images.length
		if (diff < -props.images.length / 2) return diff + props.images.length
		return diff
	}

	const getStyle = (i) => {
		const pos = getRelativeIndex(i)

		// 位移距离（间距约280rpx）
		const translateX = pos * 280
		const isCenter = pos === 0
		const width = isCenter ? 296 : 240
		const height = isCenter ? 518 : 420
		const zIndex = isCenter ? 3 : 2
		const opacity = Math.abs(pos) > 1 ? 0 : 1
		const scale = isCenter ? 1 : 1

		return {
			transform: `translateX(${translateX}rpx) scale(${scale})`,
			width: `${width}rpx`,
			height: `${height}rpx`,
			zIndex,
			opacity,
			transition: 'all 0.35s ease',
			position: 'absolute',
			top: '50%',
			left: '50%',
			transformOrigin: 'center center',
			marginTop: `-${height / 2}rpx`,
			marginLeft: `-${width / 2}rpx`,
		}
	}

	const shiftLeft = () => {
		positions.value.unshift(positions.value.pop())
	}
	const shiftRight = () => {
		positions.value.push(positions.value.shift())
	}

	let startX = 0
	const onTouchStart = (e) => {
		if (positions.value.length === 0) return
		startX = e.touches[0].clientX
	}
	
	const onTouchEnd = (e) => {
		const endX = e.changedTouches[0].clientX
		const diff = endX - startX
		if (diff > 50) {
			shiftRight()
		} else if (diff < -50) {
			shiftLeft()
		}
	}

	const onItemTap = (item) => {
		emit('onItemClick', item)
	}
</script>

<style scoped>
	.carousel-box {
		width: 750rpx;
		height: 600rpx;
		overflow: hidden;
		display: flex;
		justify-content: center;
		align-items: center;
		position: relative;
	}

	.carousel-track {
		width: 750rpx;
		height: 100%;
		position: relative;
	}

	.carousel-item {
		border-radius: 16rpx;
		overflow: hidden;
	}

	.carousel-img {
		width: 100%;
		height: 100%;
		border-radius: 16rpx;
	}
</style>